<?php
/// O'My Friends: Personal Social Network Graph on Facebook
/// author : Minkyu Shim (minkyu.shim@gmail.com
require_once 'facebookAPIHelper.php';

//return user object returned by '/me' api call
function getOneself(){
    global $facebook;
    $me = null;
    try{
        $me = callGraphAPI('/me?fields=id,link');
    } catch (FacebookApiException $e){
        throw($e);
    }
    return $me;
}

function getResultSet($queryName, &$data){
    foreach($data as $query){
        if(isset($query['name']) && $query['name'] == $queryName){
            return $query;
        }
    }
    return false;
}

/***********************************
 * Data Fetching Functions       *
 ***********************************/

//Fetching Message
function getMessage(){

    $data = null;
    
    //Queries
    $threadQuery = "SELECT thread_id, recipients FROM thread 
    				WHERE folder_id = 0 OR folder_id = 1 AND updated_time > ".QUERY_SINCE;
    
    $messageQuery = "SELECT thread_id, author_id FROM message 
    				WHERE thread_id IN (
                    	SELECT thread_id FROM #threadQuery
                	) AND created_time > ".QUERY_SINCE;
    
    $queries = array();
    $queries['threadQuery'] = $threadQuery;
    $queries['messageQuery'] = $messageQuery;
    
    try{
        $data = callMultiFQL($queries);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

//Post Functions
//    Friend Post
function getFriendPost(){
    
    $data = null;
    
    $query = "SELECT actor_id FROM stream 
                        WHERE source_id = me() AND actor_id IN (
                        	SELECT uid1 FROM friend WHERE uid2 = me()
                        ) AND created_time >".QUERY_SINCE;
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;    
}
//    My Post (*tricky*)
//    NOTE: this query fetches data from news feed which only contains data of the last 30 days. 
//          It would be more accurate if using homepage like query without filter_key and specifying a source_id
//          ex)SELECT message FROM stream WHERE actor_id = me() AND source_id = '100000525262538' 
function getMyPost(){

    $data = null;
    
    $query = "SELECT source_id FROM stream 
			WHERE filter_key = 'nf' AND source_id != me() AND actor_id = me()";
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

//Comment Functions
//    Friend Comment
//        On Status
function getFriendCommentOnStatus(){

    $data = null;
    
    $query = "SELECT fromid FROM comment
    			WHERE fromid != me() 
    			AND (
    				object_id IN (SELECT status_id FROM status WHERE uid = me() AND time > ".QUERY_SINCE.")
    			) AND time >".QUERY_SINCE;

    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
    
}
//        On Link
function getFriendCommentOnLink(){

    $data = null;
    
    $query = "SELECT fromid FROM comment
    			WHERE fromid != me() 
    			AND (
					object_id IN (SELECT link_id FROM link WHERE owner = me() AND created_time > ".QUERY_SINCE.")
    			) AND time >".QUERY_SINCE;

    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Note
function getFriendCommentOnNote(){

    $data = null;
                				
    $query = "SELECT fromid FROM comment
    			WHERE fromid != me() 
    			AND (
					object_id IN (SELECT note_id FROM note WHERE uid = me()  AND created_time > ".QUERY_SINCE.")
    			) AND time >".QUERY_SINCE;

    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Photo
function getFriendCommentOnPhoto(){
    $data = null;
                				
    $query = "SELECT fromid FROM comment
    			WHERE fromid != me() 
    			AND (
					object_id IN (SELECT pid FROM photo WHERE owner = me()  AND created > ".QUERY_SINCE.")
    			) AND time >".QUERY_SINCE;

    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

//    My Comment
//        On Status
function getMyCommentOnStatus(){
    
    $data = null;
    
    $query = "SELECT uid FROM status WHERE status_id IN (
        SELECT object_id FROM comment 
        WHERE fromid = me() AND object_id IN (
            SELECT status_id FROM status WHERE uid IN (
                SELECT uid2 FROM friend WHERE uid1 = me()
            ) AND time >".QUERY_SINCE."
        ) AND time >".QUERY_SINCE."
    )";

    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
    
}
//        On Link
function getMyCommentOnLink(){
    
    $data = null;
    
    $query = "SELECT owner FROM link WHERE link_id IN (
        SELECT object_id FROM comment 
        WHERE fromid = me() AND object_id IN (
            SELECT link_id FROM link WHERE owner IN (
                SELECT uid2 FROM friend WHERE uid1 = me()
            ) AND created_time > ".QUERY_SINCE."
        ) AND time >".QUERY_SINCE."
    )";
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
    
}
//        On Note
function getMyCommentOnNote(){
    
    $data = null;
    
    $query = "SELECT uid FROM note WHERE note_id IN (
        SELECT object_id FROM comment 
        WHERE fromid = me() AND object_id IN (
            SELECT note_id FROM note WHERE uid IN (
                SELECT uid2 FROM friend WHERE uid1 = me()
            )AND created_time > ".QUERY_SINCE."
        ) AND time >".QUERY_SINCE."
    )";
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
    
}
//        On Photo
function getMyCommentOnPhoto(){
    
    $data = null;
    
    $query = "SELECT owner FROM photo WHERE pid IN (
        SELECT object_id FROM comment 
        WHERE fromid = me() AND object_id IN (
            SELECT pid FROM photo WHERE owner IN (
                SELECT uid2 FROM friend WHERE uid1 = me()
            ) AND created >".QUERY_SINCE."
        ) AND time >".QUERY_SINCE."
    )";
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

//Like Functions
//    Friend Like
//        On Status
function getFriendLikeOnStatus(){
    
    $data = null;
    
    $query = "SELECT user_id FROM like 
        			WHERE user_id != me() 
        			AND (
        				object_id IN (SELECT status_id FROM status WHERE uid = me() AND time > ".QUERY_SINCE.")
        			)";
    
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Link
function getFriendLikeOnLink(){
    
    $data = null;
    
    $query = "SELECT user_id FROM like 
        			WHERE user_id != me() 
        			AND (
        				object_id IN (SELECT link_id FROM link WHERE owner = me() AND created_time > ".QUERY_SINCE.")
        			)";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Note
function getFriendLikeOnNote(){

    $data = null;
    
    $query = "SELECT user_id FROM like 
    			WHERE user_id != me() 
    			AND (
    				object_id IN (SELECT note_id FROM note WHERE uid = me() AND created_time > ".QUERY_SINCE.")
    			)";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Photo
function getFriendLikeOnPhoto(){

    $data = null;
    
    $query = "SELECT user_id FROM like 
    			WHERE user_id != me() 
    			AND (
    				object_id IN (SELECT pid FROM photo WHERE owner = me() AND created > ".QUERY_SINCE.")
    			)";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

//    My Like
//        On Status
function getMyLikeOnStatus(){

    $data = null;

    $query = "SELECT uid FROM status WHERE status_id IN (
                        SELECT object_id FROM like 
                        WHERE user_id = me() AND object_id IN (
                            SELECT status_id FROM status WHERE uid IN (
                                SELECT uid2 FROM friend WHERE uid1 = me()
                            ) AND time > ".QUERY_SINCE."
                        )
                    )";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;


}
//        On Link
function getMyLikeOnLink(){

    $data = null;
    
    $query = "SELECT owner FROM link WHERE link_id IN (
                    SELECT object_id FROM like 
                    WHERE user_id = me() AND object_id IN (
                        SELECT link_id FROM link WHERE owner IN (
                            SELECT uid2 FROM friend WHERE uid1 = me()
                        ) AND created_time > ".QUERY_SINCE."
                    )
                )";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}
//        On Note
function getMyLikeOnNote(){
    
    $data = null;
    $query = "SELECT uid FROM note WHERE note_id IN (
                    SELECT object_id FROM like 
                    WHERE user_id = me() AND object_id IN (
                        SELECT note_id FROM note WHERE uid IN (
                            SELECT uid2 FROM friend WHERE uid1 = me()
                        ) AND created_time > ".QUERY_SINCE."
                    )
                )";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
    
}
//        On Photo
function getMyLikeOnPhoto(){

    $data = null;
    $query = "SELECT owner FROM photo WHERE pid IN (
                SELECT object_id FROM like 
                WHERE user_id = me() AND object_id IN (
                    SELECT pid FROM photo WHERE owner IN (
                        SELECT uid2 FROM friend WHERE uid1 = me()
                    ) AND created > ".QUERY_SINCE."
                )
            )";
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw $e;
    }
    
    return $data;
}

/***********************************
 * Data Processing Functions       *
 ***********************************/

//Message Processing Functions
function processMessage(&$friends, &$threads, &$messages){

    global $session;
    
    if(isset($threads['fql_result_set'])){
        $threads = $threads['fql_result_set'];
    }
    if(isset($messages['fql_result_set'])){
        $messages = $messages['fql_result_set'];
    }
    
    //parse data and create new thread array
    //$threadData = array(
    //             'thread_id' => array( 'sender' => sender_id , 'recipients' => recipients array)
    //)
    $threadData = array();
    foreach($threads as $thread){
        //Ignore duplicated thread
        if(!array_key_exists($thread['thread_id'], $threadData)){

            //first recipient is the sender
            $threadData[$thread['thread_id']]['sender'] = $thread['recipients'][0];
            
            //if the user oneself is the sender
            if($thread['recipients'][0] == $session['uid']){
                //remove the person from recipients array
                $threadData[$thread['thread_id']]['recipients'] = array_slice($thread['recipients'], 1);                    
            } else {
                //if the user is one of recipients, ignore other recipients
                $threadData[$thread['thread_id']]['recipients'] = array($session['uid']);
            }

        }
    }

    //$repliers = array(thread_id => replier array);
    $repliers = array();
    foreach($messages as $message){
        //if the thread is already added
        if(array_key_exists($message['thread_id'], $repliers)){
            //check if the person is already in the repliers
            if(!in_array($message['author_id'], $repliers[$message['thread_id']])){
                //add replier
                $repliers[$message['thread_id']][] = $message['author_id'];
            }
        }
        //if the thread is not in the array
        else{
            //create an array
            $repliers[$message['thread_id']] = array($message['author_id']);
        }
    }
    
    //This is probably the most tricky code in the application.
    foreach($threadData as $thread_id => $thread){
        //if sender is oneself
        if($thread['sender'] == $session['uid']){
            foreach($thread['recipients'] as $recipient){
                
                if(array_key_exists($thread_id, $repliers) && in_array($recipient, $repliers[$thread_id])){
                    //there is the friend in the array
                    if(isset($friends[$recipient]) && $friends[$recipient] instanceof Friend){
                        $friends[$recipient]->increaseTwoWayMessages();
                    }else{
                        //if the friend is new, first create and increase and push
                        $f = new Friend($recipient, null);
                        $f->increaseTwoWayMessages();

                        $friends[$recipient] = $f;
                    }
                } else {
                    if(isset($friends[$recipient]) && $friends[$recipient] instanceof Friend){
                        $friends[$recipient]->increaseOneWayMessages();
                    }else{
                        //if the friend is new, first create and increase and push
                        $f = new Friend($recipient, null);
                        $f->increaseOneWayMessages();
                        $friends[$recipient] = $f;
                    }
                }
            }
        }
        //if sender is a friend, try to find myself among the repliers otherwise the sender count one-way
        else{
            if(array_key_exists($thread_id, $repliers) && in_array($session['uid'], $repliers[$thread_id])){
                if(isset($friends[$thread['sender']]) && $friends[$thread['sender']] instanceof Friend){
                    $friends[$thread['sender']]->increaseTwoWayMessages();
                }else{
                    //if the friend is new, first create and increase and push
                    $f = new Friend($thread['sender'], null);
                    $f->increaseTwoWayMessages();
                    $friends[$thread['sender']] = $f;
                }
            } else {
                if(isset($friends[$thread['sender']]) && $friends[$thread['sender']] instanceof Friend){
                    $friends[$thread['sender']]->increaseOneWayMessages();
                }else{
                    $f = new Friend($thread['sender'], null);
                    $f->increaseOneWayMessages();
                    $friends[$thread['sender']] = $f;
                }
            }
        }
    }    
    return $friends;
}

//Post Processing Functions
function processPost(&$friends, $posts){

    if(is_array($posts) && !empty($posts)){
        foreach($posts as $post){
            
            $fId = null;
            if(isset($post['actor_id'])){
                $fId = $post['actor_id'];    
            }elseif(isset($post['source_id'])){
                $fId = $post['source_id'];
            }
            if(!is_null($fId)){
                if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                    $friends[$fId]->increasePosts();
                } else {
                    $f = new Friend($fId, null);
                    $f->increasePosts();
                    $friends[$fId] = $f;
                }
            }
        }
    }
    return $friends;
}

//    Friend Post
function processFriendPost(&$friends, $posts){
    processPost($friends, $posts);
}

//    My Post
function processMyPost(&$friends, $posts){
    processPost($friends, $posts);
}

//Comment Processing Functions
//    Friend Comment
function processFriendComment(&$friends, &$comments){
    
    if(!empty($comments) && is_array($comments)){
        foreach ($comments as $comment){
            $fId = $comment['fromid'];
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseComments();
            } else {
                $f = new Friend($fId, null);
                $f->increaseComments();
                $friends[$fId] = $f;
            }
        }
    }
}
//        On Status
function processFriendCommentOnStatus(&$friends, &$comments){
    processFriendComment($friends, $comments);
}
//        On Link
function processFriendCommentOnLink(&$friends, &$comments){
    processFriendComment($friends, $comments);
}
//        On Note
function processFriendCommentOnNote(&$friends, &$comments){
    processFriendComment($friends, $comments);
}
//        On Photo
function processFriendCommentOnPhoto(&$friends, &$comments){
    processFriendComment($friends, $comments);
}

//    My Comment
function processMyComment(&$friends, $comments){
    
    if(!empty($comments) && is_array($comments)){
        foreach($comments as $comment){
            $fId = array_pop($comment);
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseComments();
            } else {
                $f = new Friend($fId, null);
                $f->increaseComments();
                $friends[$fId] = $f;
            }
        }
    }
    return $friends;
}
//        On Status
function processMyCommentOnStatus(&$friends, $comments){
    return processMyComment($friends, $comments);
}
//        On Link
function processMyCommentOnLink(&$friends, $comments){
    return processMyComment($friends, $comments);
}
//        On Note
function processMyCommentOnNote(&$friends, $comments){
    return processMyComment($friends, $comments);
}
//        On Photo
function processMyCommentOnPhoto(&$friends, $comments){
    return processMyComment($friends, $comments);
}

//Like Processing Functions
//    Friend Like
function processFriendLike(&$friends, $likes){
    
    if(!empty($likes) && is_array($likes)){
        foreach ($likes as $like){
            $fId = $like['user_id'];
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseLikes();
            } else {
                $f = new Friend($fId, null);
                $f->increaseLikes();
                $friends[$fId] = $f;
            }
        }
    }
    return $friends;
}
//        On Status
function processFriendLikeOnStatus(&$friends, $likes){
    return processFriendLike($friends, $likes);
}
//        On Link
function processFriendLikeOnLink(&$friends, $likes){
    return processFriendLike($friends, $likes);
}
//        On Note
function processFriendLikeOnNote(&$friends, $likes){
    return processFriendLike($friends, $likes);
}
//        On Photo
function processFriendLikeOnPhoto(&$friends, $likes){
    return processFriendLike($friends, $likes);
}
//    My Like
function processMyLike(&$friends, $likes){
    
    foreach($likes as $likes){
        $fId = array_pop($likes);
        if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
            $friends[$fId]->increaseLikes();
        } else {
            $f = new Friend($fId, null);
            $f->increaseLikes();
            $friends[$fId] = $f;
        }
    }
    return $friends;
}

//        On Status
function processMyLikeOnStatus(&$friends, $likes){
    return processMyLike($friends, $likes);
}
//        On Link
function processMyLikeOnLink(&$friends, $likes){
    return processMyLike($friends, $likes);
}
//        On Note
function processMyLikeOnNote(&$friends, $likes){
    return processMyLike($friends, $likes);
}
//        On Photo
function processMyLikeOnPhoto(&$friends, $likes){
    return processMyLike($friends, $likes);
}


//get all activity data for a friend
//param $id : a friend's id
//return $data : result of multiquery
//exception : FacebookApiException
function getActivities($id){
    //messages, post(note, link, status, comment)
    $data = null;
    
    try{
    
        $inMessageQuery = "SELECT message_id, thread_id, author_id, body, created_time FROM message WHERE author_id = '$id' AND thread_id IN (
                            	SELECT thread_id FROM thread WHERE folder_id = 0 AND updated_time > ".QUERY_SINCE."
                        	) AND created_time > ".QUERY_SINCE;
        
        $outMessageQuery = "SELECT message_id, thread_id, author_id, body, created_time FROM message WHERE author_id = me() AND thread_id IN (
                    	SELECT thread_id FROM thread WHERE folder_id = 1 AND updated_time > ".QUERY_SINCE."
                	) AND created_time > ".QUERY_SINCE;
            
        $outThreadQuery = "SELECT thread_id, recipients, subject FROM thread WHERE folder_id = 1 AND thread_id IN (
                            	SELECT thread_id FROM #outMessageQuery
                            )";
        
        $friendCommentQuery = "SELECT object_id, fromid, text, time FROM comment
            			WHERE fromid = '$id' 
            			AND (
            				object_id IN (SELECT note_id FROM note WHERE uid = me() AND created_time > ".QUERY_SINCE.")
            				OR object_id IN (SELECT status_id FROM status WHERE uid = me() AND time > ".QUERY_SINCE.")
            				OR object_id IN (SELECT link_id FROM link WHERE owner = me() AND created_time > ".QUERY_SINCE.")
            			) AND time >".QUERY_SINCE; 
        
        $myCommentQuery = "SELECT object_id, fromid, text, time FROM comment 
                WHERE fromid = me() 
                AND (
    				object_id IN (SELECT note_id FROM note WHERE uid = '$id' AND created_time > ".QUERY_SINCE.")
    				OR object_id IN (SELECT status_id FROM status WHERE uid = '$id' AND time > ".QUERY_SINCE.")
    				OR object_id IN (SELECT link_id FROM link WHERE owner = '$id' AND created_time > ".QUERY_SINCE.")
                ) AND time >".QUERY_SINCE; 

        $friendPostQuery = "SELECT post_id, actor_id, message, created_time FROM stream 
                        WHERE source_id = me() AND actor_id = '$id' AND created_time >".QUERY_SINCE;

        $data = callMultiFQL(array(
            'inMessageQuery'      => $inMessageQuery, 
            'outMessageQuery'     => $outMessageQuery,
            'outThreadQuery'      => $outThreadQuery,
            'friendCommentQuery' => $friendCommentQuery,
            'myCommentQuery'      => $myCommentQuery,
            'friendPostQuery'     => $friendPostQuery
        ));

    }catch(FacebookApiException $e){
        throw($e);
    }
    return $data;       
}
/*
//return an array of Friend objects
function getFriends(){

    try{
        $response = callGraphAPI('/me/friends');
    }catch(FacebookApiException $e){
        throw($e);
    }
    $arr = Array();
    if(!empty($response['data'])){
        $friends = $response['data'];

        foreach ($friends as $friend) {
            $f = new Friend($friend['id'], $friend['name']);
            $arr[$friend['id']] = $f;
        }
    }
    return $arr;
}

//get all data using Multiquery
//param $mode : flags (1:Message, 2:Post, 4:Comment, 8:Like And flags can be added for example, 1+2 = 3 : Message+Post flags)
//return $data
function getAllDataFromFQL(){

    $args = func_get_args();
    if(isset($args['0'])){
        $mode = $args['0'];
    }else{
        $mode = 0;
    }

    $data = null;
    
    try{
    
        $queries = array();
        
        if(($mode & MESSAGE_FLAG) === MESSAGE_FLAG){
            //MESSAGE QUERIES
            
            $threadQuery = "select thread_id, recipients from thread where folder_id = 0 or folder_id = 1 and updated_time > ".QUERY_SINCE;
            
            $messageQuery = "select thread_id, author_id from message where thread_id in (
                            	select thread_id from #threadQuery
                        	) and created_time > ".QUERY_SINCE;
            
            $queries['threadQuery'] = $threadQuery;
            $queries['messageQuery'] = $messageQuery;
        }
        
        if(($mode & POST_FLAG) === POST_FLAG){
            //POST QUERY
            //Friends' posts on my wall
            $friendsPostQuery = "SELECT actor_id FROM stream 
                                WHERE source_id = me() AND actor_id IN (
                                	SELECT uid1 FROM friend WHERE uid2 = me()
                                ) AND created_time >".QUERY_SINCE;
            
            $queries['friendsPostQuery'] = $friendsPostQuery;
        }
        
        if(($mode & FRIEND_COMMENT_FLAG) === FRIEND_COMMENT_FLAG){
            //COMMENTS QUERIES
            //Friends' comments on my post
            $friendsCommentQuery = "SELECT fromid FROM comment
                			WHERE fromid != me() 
                			AND (
                				object_id IN (SELECT note_id FROM note WHERE uid = me()  AND created_time > ".QUERY_SINCE.")
                				OR object_id IN (SELECT status_id FROM status WHERE uid = me() AND time > ".QUERY_SINCE.")
                				OR object_id IN (SELECT link_id FROM link WHERE owner = me() AND created_time > ".QUERY_SINCE.")
                			) AND time >".QUERY_SINCE;

            $queries['friendsCommentQuery'] = $friendsCommentQuery;
        }

        if(($mode & FRIEND_LIKE_FLAG) === FRIEND_LIKE_FLAG){
            //LIKES QUERIES
            //Friends' likes
            $friendsLikesQuery = "SELECT user_id FROM like 
                			WHERE user_id != me() 
                			AND (
                				object_id IN (SELECT note_id FROM note WHERE uid = me() AND created_time > ".QUERY_SINCE.")
                				OR object_id IN (SELECT status_id FROM status WHERE uid = me() AND time > ".QUERY_SINCE.")
                				OR object_id IN (SELECT link_id FROM link WHERE owner = me() AND created_time > ".QUERY_SINCE.")
                			)";

            $queries['friendsLikesQuery'] = $friendsLikesQuery;
        }
        
        if(($mode & MY_NOTE_COMMENT_FLAG) === MY_NOTE_COMMENT_FLAG ){        
            //MY COMMENTS ON NOTES OF FRIENDS
            $myCommentNoteQuery = "SELECT uid FROM note WHERE note_id IN (
                SELECT object_id FROM comment 
                WHERE fromid = me() AND object_id IN (
                    SELECT note_id FROM note WHERE uid IN (
                        SELECT uid2 FROM friend WHERE uid1 = me()
                    )
                ) AND time >".QUERY_SINCE."
            )";
            $queries['myCommentNoteQuery'] = $myCommentNoteQuery;
        }
        
        if(($mode & MY_STATUS_COMMENT_FLAG) === MY_STATUS_COMMENT_FLAG ){
            //MY COMMENTS ON STATUSES OF FRIENDS
            $myCommentStatusQuery = "SELECT uid FROM status WHERE status_id IN (
                SELECT object_id FROM comment 
                WHERE fromid = me() AND object_id IN (
                    SELECT status_id FROM status WHERE uid IN (
                        SELECT uid2 FROM friend WHERE uid1 = me()
                    )
                ) AND time >".QUERY_SINCE."
            )";
            $queries['myCommentStatusQuery'] = $myCommentStatusQuery;
        }
        
        if(($mode & MY_LINK_COMMENT_FLAG) === MY_LINK_COMMENT_FLAG ){
            //MY COMMENTS ON LINKS OF FRIENDS
            $myCommentLinkQuery = "SELECT owner FROM link WHERE link_id IN (
                SELECT object_id FROM comment 
                WHERE fromid = me() AND object_id IN (
                    SELECT link_id FROM link WHERE owner IN (
                        SELECT uid2 FROM friend WHERE uid1 = me()
                    )
                ) AND time >".QUERY_SINCE."
            )";
            $queries['myCommentLinkQuery'] = $myCommentLinkQuery;
     
        }
        
        if(($mode & MY_LIKE_FLAG) === MY_LIKE_FLAG){
            //My likes
            $myLikeNoteQuery = "SELECT uid FROM note WHERE note_id IN (
                                SELECT object_id FROM like 
                                WHERE user_id = me() AND object_id IN (
                                    SELECT note_id FROM note WHERE uid IN (
                                        SELECT uid2 FROM friend WHERE uid1 = me()
                                    ) AND created_time > ".QUERY_SINCE."
                                )
                            )";
            $queries['myLikeNoteQuery'] = $myLikeNoteQuery;
            
            $myLikeStatusQuery = "SELECT uid FROM status WHERE status_id IN (
                                SELECT object_id FROM like 
                                WHERE user_id = me() AND object_id IN (
                                    SELECT status_id FROM status WHERE uid IN (
                                        SELECT uid2 FROM friend WHERE uid1 = me()
                                    ) AND time > ".QUERY_SINCE."
                                )
                            )";
            $queries['myLikeStatusQuery'] = $myLikeStatusQuery;
            
            $myLikeLinkQuery = "SELECT owner FROM link WHERE link_id IN (
                                SELECT object_id FROM like 
                                WHERE user_id = me() AND object_id IN (
                                    SELECT link_id FROM link WHERE owner IN (
                                        SELECT uid2 FROM friend WHERE uid1 = me()
                                    ) AND created_time > ".QUERY_SINCE."
                                )
                            )";
            $queries['myLikeLinkQuery'] = $myLikeLinkQuery;            


        }
        
        $data = callMultiFQL($queries);
        
    }catch(FacebookApiException $e){
        throw($e);
    }
    return $data;    
}




function getFriendsOfFriends(){
    
    $query = "select uid1, uid2 from friend 
    	where uid1 IN (
    		select uid1 from friend where uid2 = me()
    	) and uid2 IN (
    		select uid1 from friend where uid2 = me()
    	) ";
    
    $data = null;
    try{
        $data = callFQL($query);
    }catch(FacebookApiException $e){
        throw($e);
    }
    return $data;
}



//parse data and add Activities into input parameter,
function getInMessageActivities($data, &$activities){
    
    //check if it's raw data
    if(isset($data['fql_result_set'])){
        $data = $data['fql_result_set'];
    }
    
    //fill the array
    if(is_array($data) && !empty($data)){
        foreach($data as $message){
            $act = new activity($message['message_id'], "msg", $message['author_id'], str_replace("\n", "", substr($message['body'],0,STRING_LENGTH)), $message['created_time']);
            array_push($activities, $act);
        }
    }
    return $activities;
}

//parse out messages and threads to extract recipients data
//in case of out messages, which is different from in messages, it's impossible to get data from only recipient id
//It can't be helped that get all out messages regardless of recipients, then parse data to extract recipient data later
function getOutMessageActivities($id, $messages, $threads, &$activities){

    //check input $activities is an array
    if(!is_array($activities)){
        return false;
    }
    //check raw data
    if($messages['name'] == "outMessageQuery" && isset($messages['fql_result_set']) && $threads['name'] == "outThreadQuery" && isset($threads['fql_result_set'])){
        $messages = $messages['fql_result_set'];
        $threads = $threads['fql_result_set'];
    } else {
        return false;
    }
    
    //fill the array
    if(is_array($messages) && is_array($threads) && !empty($messages) && !empty($threads)){

        //first check threads sent to the id
        foreach($threads as $thread){
            $recipients = $thread['recipients'];
            $thread_id = $thread['thread_id'];
            foreach($recipients as $recipient){
                if($recipient == $id){
                    //find messages in $thread_id
                    foreach($messages as $message){
                        if($message['thread_id'] == $thread_id){
                            $act = new activity($message['message_id'], "msg", $message['author_id'], str_replace("\n", "", substr($message['body'],0,STRING_LENGTH)), $message['created_time']);
                            array_push($activities, $act);
                        }
                    } 
                }
            }
        }
        
    }
    
    return $activities;
    
    
}

//parse the friend's post data then return activities array
function getFriendPostActivities($data, &$activities){
    //check input $activities is an array
    if(!is_array($activities)){
        return false;
    }
    //check raw data
    if($data['name'] == "friendPostQuery" && isset($data['fql_result_set'])){
        $data = $data['fql_result_set'];
    } else {
        return false;
    }
    
    //fill out the array
    if(is_array($data) && !empty($data)){
        foreach($data as $post){
            $act = new activity($post['post_id'], "post", $post['actor_id'], $post['message'], $post['created_time']);
            array_push($activities, $act);
        }
    }
    return $activities;
}

//parse the friend's comment data then return activities array
function getFriendCommentActivities($data, &$activities){
    //check input $activities is an array
    if(!is_array($activities)){
        return false;
    }
    //check raw data
    if($data['name'] == "friendCommentQuery" && isset($data['fql_result_set'])){
        $data = $data['fql_result_set'];
    } else {
        return false;
    }
    if(is_array($data) && !empty($data)){
        foreach($data as $comment){
            $act = new activity($comment['object_id'], "comment", $comment['fromid'], str_replace("\n", "", substr($comment['text'],0,STRING_LENGTH)), $comment['time']);
            array_push($activities, $act);        
        }
    }
    return $activities;
}

//parse my comments on the friend's posts, fill out activities array then return it
function getMyCommentActivities($data, &$activities){
    //check input $activities is an array
    if(!is_array($activities)){
        return false;
    }
    //check raw data
    if($data['name'] == "myCommentQuery" && isset($data['fql_result_set'])){
        $data = $data['fql_result_set'];
    } else {
        return false;
    }
    
    //fill out the array
    foreach($data as $comment){
        $act = new activity($comment['object_id'], "comment", $comment['fromid'], str_replace("\n", "", substr($comment['text'],0,STRING_LENGTH)), $comment['time']);
        array_push($activities, $act);
    }
    return $activities;
    
}

//Get thread, message data and parsing the data and fill empty friends array with relevant information
function processMessages(&$friends, &$threads, &$messages){

    global $session;
    
    if(isset($threads['fql_result_set'])){
        $threads = $threads['fql_result_set'];
    }
    if(isset($messages['fql_result_set'])){
        $messages = $messages['fql_result_set'];
    }
    
    //parse data and create new thread array
    //$threadData = array(
    //             'thread_id' => array( 'sender' => sender_id , 'recipients' => recipients array)
    //)
    $threadData = array();
    foreach($threads as $thread){
        //Ignore duplicated thread
        if(!array_key_exists($thread['thread_id'], $threadData)){

            //first recipient is the sender
            $threadData[$thread['thread_id']]['sender'] = $thread['recipients'][0];
            
            //if the user oneself is the sender
            if($thread['recipients'][0] == $session['uid']){
                //remove the person from recipients array
                $threadData[$thread['thread_id']]['recipients'] = array_slice($thread['recipients'], 1);                    
            } else {
                //if the user is one of recipients, ignore other recipients
                $threadData[$thread['thread_id']]['recipients'] = array($session['uid']);
            }

        }
    }

    //$repliers = array(thread_id => replier array);
    $repliers = array();
    foreach($messages as $message){
        //if the thread is already added
        if(array_key_exists($message['thread_id'], $repliers)){
            //check if the person is already in the repliers
            if(!in_array($message['author_id'], $repliers[$message['thread_id']])){
                //add replier
                $repliers[$message['thread_id']][] = $message['author_id'];
            }
        }
        //if the thread is not in the array
        else{
            //create an array
            $repliers[$message['thread_id']] = array($message['author_id']);
        }
    }
    
    //This is probably the most tricky code in the application.
    foreach($threadData as $thread_id => $thread){
        //if sender is oneself
        if($thread['sender'] == $session['uid']){
            foreach($thread['recipients'] as $recipient){
                
                if(array_key_exists($thread_id, $repliers) && in_array($recipient, $repliers[$thread_id])){
                    //there is the friend in the array
                    if(isset($friends[$recipient]) && $friends[$recipient] instanceof Friend){
                        $friends[$recipient]->increaseTwoWayMessages();
                    }else{
                        //if the friend is new, first create and increase and push
                        $f = new Friend($recipient, null);
                        $f->increaseTwoWayMessages();

                        $friends[$recipient] = $f;
                    }
                } else {
                    if(isset($friends[$recipient]) && $friends[$recipient] instanceof Friend){
                        $friends[$recipient]->increaseOneWayMessages();
                    }else{
                        //if the friend is new, first create and increase and push
                        $f = new Friend($recipient, null);
                        $f->increaseOneWayMessages();
                        $friends[$recipient] = $f;
                    }
                }
            }
        }
        //if sender is a friend, try to find myself among the repliers otherwise the sender count one-way
        else{
            if(array_key_exists($thread_id, $repliers) && in_array($session['uid'], $repliers[$thread_id])){
                if(isset($friends[$thread['sender']]) && $friends[$thread['sender']] instanceof Friend){
                    $friends[$thread['sender']]->increaseTwoWayMessages();
                }else{
                    //if the friend is new, first create and increase and push
                    $f = new Friend($thread['sender'], null);
                    $f->increaseTwoWayMessages();
                    $friends[$thread['sender']] = $f;
                }
            } else {
                if(isset($friends[$thread['sender']]) && $friends[$thread['sender']] instanceof Friend){
                    $friends[$thread['sender']]->increaseOneWayMessages();
                }else{
                    $f = new Friend($thread['sender'], null);
                    $f->increaseOneWayMessages();
                    $friends[$thread['sender']] = $f;
                }
            }
        }
    }    
    
}

//Processing friends' comments on my posts
function processFriendsComments(&$friends, &$comments){
    
    if(isset($comments['fql_result_set'])){
        $comments = $comments['fql_result_set'];
    }
    
    if(!empty($comments) && is_array($comments)){
        foreach ($comments as $comment){
            $fId = $comment['fromid'];
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseComments();
            } else {
                $f = new Friend($fId, null);
                $f->increaseComments();
                //array_push($friends, $f);
                $friends[$fId] = $f;
            }
        }
    }
}

//Deprecated
//Processing my comments on friends' posts
function processMyComments(&$friends, $object_array){

    if(!empty($object_array) && is_array($object_array)){
        foreach ($object_array as $objects){
            if(!empty($objects['fql_result_set']) && is_array($objects['fql_result_set'])){
                foreach($objects['fql_result_set'] as $object){
                    $fId = array_pop($object);
                    if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                        $friends[$fId]->increaseComments();
                    } else {
                        $f = new Friend($fId, null);
                        $f->increaseComments();
                        //array_push($friends, $f);
                        $friends[$fId] = $f;
                    }
                }
            }
        }
    }
}

//Processing my comments on friends' note
function processMyComments2(&$friends, $comments){
    
    if(isset($comments['fql_result_set'])){
        $comments = $comments['fql_result_set'];
    }
    
    if(!empty($comments) && is_array($comments)){
        foreach($comments as $comment){
            $fId = array_pop($comment);
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseComments();
            } else {
                $f = new Friend($fId, null);
                $f->increaseComments();
                //array_push($friends, $f);
                $friends[$fId] = $f;
            }
        }
    }
}

function processFriendsLikes(&$friends, $likes){
    
    if(isset($likes['fql_result_set'])){
        $likes = $likes['fql_result_set'];
    }
    
    if(!empty($likes) && is_array($likes)){
        foreach ($likes as $like){
            $fId = $like['user_id'];
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increaseLikes();
            } else {
                $f = new Friend($fId, null);
                $f->increaseLikes();
                //array_push($friends, $f);
                $friends[$fId] = $f;
            }
        }
    }    
}

function processMyLikes(&$friends, $object_array){
    if(!empty($object_array) && is_array($object_array)){
        foreach ($object_array as $objects){
            if(!empty($objects['fql_result_set']) && is_array($objects['fql_result_set'])){
                foreach($objects['fql_result_set'] as $object){
                    $fId = array_pop($object);
                    if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                        $friends[$fId]->increaseLikes();
                    } else {
                        $f = new Friend($fId, null);
                        $f->increaseLikes();
                        //array_push($friends, $f);
                        $friends[$fId] = $f;
                    }
                }
            }
        }
    }
}

function processFriendsPostsOnMyWall(&$friends, $posts){
    if($posts['name'] == "friendsPostQuery" && isset($posts['fql_result_set'])){
        $posts = $posts['fql_result_set'];
    }
    if(is_array($posts) && !empty($posts)){
        foreach($posts as $post){
            $fId = $post['actor_id'];
            if(isset($friends[$fId]) && ($friends[$fId] instanceof Friend)){
                $friends[$fId]->increasePosts();
            } else {
                $f = new Friend($fId, null);
                $f->increaseLikes();
                //array_push($friends, $f);
                $friends[$fId] = $f;
            }
        }
    }
}


//Check if the current session is valid by making a simple api call and get $me back
//if it's valid return true otherwise return false;
function checkSessionValidity(){
    global $facebook;
    if(getOneself()){
        return true;
    }
    return false;
}



//get wall posts
//param : $uid (Facebook user id)
function getWallPosts($uid){
    global $facebook;
    $posts = null;

    try{
        $response= $facebook->api('/'.$uid.'/feed?fields=from,comments&since='.QUERY_SINCE);
        //$response= $facebook->api('/'.$uid.'/feed?limit=3');
        if(!empty($response['data'])){
            $posts = $response['data'];
        }
    }catch(FacebookApiException $e){
        throw($e);
    }

    return $posts;   
}

function processingWallPostsOnMyWall(&$friends){
    
    global $me;
    $posts = getWallPosts($me['id']);
  
    if(!empty($posts)){
        foreach($posts as $post){
            //if it's friends' posts
            if($me['id'] != $post['from']['id']){
                $fId = $post['from']['id'];
                $flag = 1;
                
                //check comments if there is a comment from me
                $comments = getComments($post['id']);
                if(existFromId($comments, $me['id'])){
                    $flag = 2;
                }
                
                //increase relevant communication number
                if($flag == 2){
                    $friends[$fId]->increasePosts();
                } else {
                    $friends[$fId]->increasePosts();
                }
                
            } else {
                //if it's my posts
                //check comments if there is a comment from friends
                $comments = getComments($post['id']);
                if(!empty($comments)){
                    foreach($comments as $comment){
                        if(!empty($comment['from']['id']) && $comment['from']['id'] != $me['id']){
                            $fId = $comment['from']['id'];
                            $friend = $friends[$fId];
                            if(!empty($friend) && $friend instanceof Friend){
                                $friends[$fId]->increasePosts();
                            }
                        }
                    }
                }
            }
        }
    }        

}

function existFromId($comments, $id){
    if(!empty($comments)){
        foreach($comments as $comment){
            if(!empty($comment['from']['id']) && $id == $comment['from']['id']){
                return true;
            }
        }
    }
    return false;
}
*/